cmake_minimum_required(VERSION 3.5)
project(TPUKernelSamples LANGUAGES C CXX)
option(CMODEL "Enable cmodel mode" OFF)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

function(parse_list INPUT OUTPUT CHAR)
  string(REGEX REPLACE ":" "${CHAR}" TMP_LIST "${INPUT}")
  set(${OUTPUT} ${TMP_LIST} PARENT_SCOPE)
endfunction()

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,--no-undefined")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--no-undefined")

if(NOT DEFINED ENV{PPL_PROJECT_ROOT})
  message(FATAL_ERROR "Please set environ PPL_PROJECT_ROOT to ppl release path")
else()
  set(PPL_TOP $ENV{PPL_PROJECT_ROOT})
  message(NOTICE "PPL_PATH: ${PPL_TOP}")
endif()

if(NOT DEFINED CHIP)
  message(FATAL_ERROR "Please set -DCHIP to chip type")
else()
  message(NOTICE "CHIP: ${CHIP}")
endif()

if(CMODEL)
  add_definitions(-DUSING_CMODEL)
  set(NAME_SUFFIX _${CHIP}_cmodel)
else()  # soc pcie
  set(NAME_SUFFIX _${CHIP})
  # try download cross toolchain
  if(NOT DEFINED ENV{CROSS_TOOLCHAINS})
      message("CROSS_TOOLCHAINS was not defined, try source download_toolchain.sh")
      execute_process(
          COMMAND bash -c "CHIP=${CHIP} DEV_MODE=${DEV_MODE} source  ${CMAKE_CURRENT_LIST_DIR}/download_toolchain.sh && env"
          RESULT_VARIABLE result
          OUTPUT_VARIABLE output
      )
      if(NOT result EQUAL "0")
          message(FATAL_ERROR "Not able to source download_toolchain.sh: ${output}")
      endif()
      string(REGEX MATCH "CROSS_TOOLCHAINS=([^\n]*)" _ ${output})
      set(ENV{CROSS_TOOLCHAINS} "${CMAKE_MATCH_1}")
  endif()

  if(${CHIP} STREQUAL "bm1688" OR ${CHIP} STREQUAL "bm1690")
    set(CMAKE_C_COMPILER $ENV{CROSS_TOOLCHAINS}/Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.6.1/bin/riscv64-unknown-linux-gnu-gcc)
  else()
    set(CMAKE_C_COMPILER $ENV{CROSS_TOOLCHAINS}/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc)
  endif()
  if(NOT EXISTS ${CMAKE_C_COMPILER})
    message("CROSS_TOOLCHAINS was not defined, try source download_toolchain.sh")
    execute_process(
        COMMAND bash -c "CHIP=${CHIP} DEV_MODE=${DEV_MODE} source  ${CMAKE_CURRENT_LIST_DIR}/download_toolchain.sh && env"
        RESULT_VARIABLE result
        OUTPUT_VARIABLE output
    )
    if(NOT result EQUAL "0")
        message(FATAL_ERROR "Not able to source download_toolchain.sh: ${output}")
    endif()
    string(REGEX MATCH "CROSS_TOOLCHAINS=([^\n]*)" _ ${output})
    set(ENV{CROSS_TOOLCHAINS} "${CMAKE_MATCH_1}")
  endif()
endif()

if(DEBUG)
  MESSAGE (STATUS "Current is Debug mode")
  set(CMAKE_BUILD_TYPE "Debug")
  set(FW_DEBUG_FLAGS "-DUSING_FW_DEBUG")
  add_definitions(-DDEBUG)
else()
  set(CMAKE_BUILD_TYPE "Release")
  add_definitions(-O3)
endif()
set(LIBRARY_OUTPUT_DIRECTORY $ENV{INSTALL_PATH}/lib)
set(NNTOOLCHAIN_DIRECTORY $ENV{PROJECT_ROOT}/third_party/nntoolchain)
if(${CHIP} STREQUAL "bm1684x")
  set(CHIP_CODE "tpu_6_0")
  if(CMODEL)
    set(KERNEL_LIB ${NNTOOLCHAIN_DIRECTORY}/lib/libcmodel_1684x.a)
    set(SHARED_LIBRARY_OUTPUT_FILE libcmodel_1684x)
  else()
    set(KERNEL_LIB ${NNTOOLCHAIN_DIRECTORY}/lib/libbm1684x_kernel_module.a)
    set(SHARED_LIBRARY_OUTPUT_FILE libbm1684x_kernel_module)
  endif()
elseif(${CHIP} STREQUAL "bm1688")
  set(CHIP_CODE "tpul_6_0")
  if(CMODEL)
    set(KERNEL_LIB ${NNTOOLCHAIN_DIRECTORY}/lib/libcmodel_1688.a)
    set(SHARED_LIBRARY_OUTPUT_FILE libcmodel_1688)
  else()
    set(KERNEL_LIB ${NNTOOLCHAIN_DIRECTORY}/lib/libbmtpulv60_kernel_module.a)
    set(SHARED_LIBRARY_OUTPUT_FILE libbmtpulv60_kernel_module)
  endif()
elseif(${CHIP} STREQUAL "bm1690")
  set(CHIP_CODE "tpub_7_1")
  if(CMODEL)
    set(KERNEL_LIB ${NNTOOLCHAIN_DIRECTORY}/lib/libcmodel_bm1690.a)
    set(SHARED_LIBRARY_OUTPUT_FILE libtpuv7_emulator)
  else()
    set(KERNEL_LIB ${NNTOOLCHAIN_DIRECTORY}/lib/libbm1690_kernel_module.a)
    # set(SHARED_LIBRARY_OUTPUT_FILE libbm1690_kernel_module_test)
    set(SHARED_LIBRARY_OUTPUT_FILE libbm1690_kernel_module)
  endif()
else()
  message(FATAL_ERROR "Unknown chip type:${CHIP}")
endif()

# deal extra flags
parse_list("${EXTRA_IDIRS}" EXTRA_IDIRS ";")
parse_list("${EXTRA_LDIRS}" EXTRA_LDIRS ";")
parse_list("${EXTRA_LDFLAGS}" EXTRA_LDFLAGS ";")
parse_list("${EXTRA_CFLAGS}" EXTRA_CFLAGS " ")

# Add chip arch defination
add_definitions(-D__${CHIP_CODE}__)
include($ENV{PPL_RUNTIME_PATH}/chip/${CHIP_CODE}/config_common.cmake)
include_directories(
  include
  ${TPUKERNEL_TOP}/kernel/include
  ${CUS_TOP}/host/include
  ${CUS_TOP}/dev/utils/include
  ${CMAKE_CURRENT_SOURCE_DIR}/${BUILD_DIR}/device
)

# Set the library directories for the shared library (link tpu-mlir's)
link_directories($ENV{INSTALL_PATH}/lib)
# Set the output file for the shared library
aux_source_directory(src_dyn DYN_DEVICE_SRCS)
add_library(${SHARED_LIBRARY_OUTPUT_FILE} SHARED ${DYN_DEVICE_SRCS})
if(CMODEL)
  set(EX_LIB stdc++)
  if(${CHIP} STREQUAL "bm1690")
      list(APPEND EX_LIB -fopenmp -ldnnl)
  endif()
else()
  set(EX_LIB -Wl,-s)
  if(${CHIP} STREQUAL "bm1690")
    list(APPEND EX_LIB -ldl)
  endif()
endif()
target_link_libraries(${SHARED_LIBRARY_OUTPUT_FILE} -Wl,--whole-archive ${KERNEL_LIB} -Wl,--no-whole-archive m ${EX_LIB})
set_target_properties(${SHARED_LIBRARY_OUTPUT_FILE} PROPERTIES PREFIX "" SUFFIX ".so" COMPILE_FLAGS "-fPIC ${FW_DEBUG_FLAGS}" LINK_FLAGS "-shared")
install(TARGETS ${SHARED_LIBRARY_OUTPUT_FILE} DESTINATION lib)
if(NOT DEBUG)
  install(FILES  $<TARGET_FILE:${SHARED_LIBRARY_OUTPUT_FILE}> DESTINATION ${NNTOOLCHAIN_DIRECTORY}/ppl)
endif()
